#ifndef _INTERNAL_H
#define _INTERNAL_H

#include <stdbool.h>
#include "ast.h"

/* Translation Unit */

struct translationunit *con_tu_init();
struct translationunit *con_tu_add_enum(struct translationunit *, struct e_enumerate *);
struct translationunit *con_tu_add_var(struct translationunit *, struct v_list *);
struct translationunit *con_tu_add_event(struct translationunit *, struct f_function *);
struct translationunit *con_tu_add_function(struct translationunit *, struct f_function *);

void free_translationunit(struct translationunit *);

/* Identifier */

struct i_list *con_i_list_init(char *);
struct i_list *con_i_list_add(struct i_list *, char *);

/* Enumerate */

struct e_enumerate *con_e_base(char *, struct e_elemlist *);
struct e_enumerate *con_e_comb(char *, struct i_list *);
struct e_elemlist *con_e_elemlist_init(struct e_element *);
struct e_elemlist *con_e_elemlist_add(struct e_elemlist *, struct e_element *);
struct e_element *con_e_elem(char *, int, char *);
struct e_list *con_e_list_init();
struct e_list *con_e_list_add(struct e_list *, struct e_enumerate *);

/* Variable */

struct v_variable *con_v_variable(struct t_type *, char *);
struct v_list *con_v_list_init();
struct v_list *con_v_list_add(struct v_list *, struct v_variable *);
struct v_list *con_v_list_combine(struct v_list *, struct v_list *);
struct v_list *con_v_list_create(struct t_type *, struct i_list *);

/* Function */

struct f_function *con_f_event(char *, struct v_list *, struct s_list *);
struct f_function *con_f_function(struct t_type *, char *, struct v_list *, struct v_list *, struct s_list *);
struct f_list *con_f_list_init();
struct f_list *con_f_list_add(struct f_list *, struct f_function *);

/* Statement */

struct s_list *con_s_list_init();
struct s_list *con_s_list_add(struct s_list *, struct s_statement *);
struct s_statement *con_s_expression(struct x_expression *);
struct s_statement *con_s_if(struct x_expression *, struct s_list *);
struct s_statement *con_s_ifelse(struct x_expression *, struct s_list *, struct s_list *);
struct s_statement *con_s_while(struct x_expression *, struct s_list *);
struct s_statement *con_s_dowhile(struct s_list *, struct x_expression *);
struct s_statement *con_s_for(struct x_expression *, struct x_expression *, struct x_expression *, struct s_list *);
struct s_statement *con_s_break();
struct s_statement *con_s_continue();
struct s_statement *con_s_return(struct x_expression *);
struct s_statement *con_s_call(char *);
struct s_statement *con_s_trans(char *);
struct s_statement *con_s_input(struct x_expression *, struct x_expression *);
struct s_statement *con_s_output(struct x_expression *, char *);

/* Type Expression */

struct t_type *con_t_int();
struct t_type *con_t_bool();
struct t_type *con_t_enum(char *);
struct t_type *con_t_cont(struct t_type *);
struct t_type *con_t_array_int(struct t_type *, struct x_expression *);
struct t_type *con_t_array_enum(struct t_type *, char *);

/* Expression */

struct x_expression *con_x_un(enum x_unop, struct x_expression *);
struct x_expression *con_x_bin(enum x_binop, struct x_expression *, struct x_expression *);
struct x_expression *con_x_tri(enum x_triop, struct x_expression *, struct x_expression *, struct x_expression *);
struct x_expression *con_x_id(char *);
struct x_expression *con_x_int(int);
struct x_expression *con_x_bool(bool);
struct x_expression *con_x_call(char *, struct x_list *);
struct x_expression *con_x_array(char *, struct x_expression *);

struct x_expression *con_x_ds_random(struct t_type *);
struct x_expression *con_x_ds_value(struct x_expression *);
struct x_expression *con_x_ds_size(struct x_expression *);
struct x_expression *con_x_ds_fill(struct x_expression *);
struct x_expression *con_x_ds_shuffle(struct x_expression *);
struct x_expression *con_x_ds_peek(struct x_expression *, struct p_position *);
struct x_expression *con_x_ds_remove(struct x_expression *, struct p_position *);
struct x_expression *con_x_ds_insert(struct x_expression *, struct p_position *, struct x_expression *);
struct x_expression *con_x_ds_extract(struct x_expression *, struct x_expression *);
struct x_expression *con_x_ds_combine(struct x_list *);

struct x_list *con_x_list_init();
struct x_list *con_x_list_add(struct x_list *, struct x_expression *);

/* Position */

struct p_position *con_p_top();
struct p_position *con_p_bottom();
struct p_position *con_p_random();
struct p_position *con_p_expression(struct x_expression *);

#endif
